﻿/*
 * Copyright (C) 2012, Jesus Requejo <jesus.requejo@gmail.com> 
 * Licensed under Microsoft Public License (Ms-PL)
 * http://www.microsoft.com/en-us/openness/licenses.aspx#MPL
*/

namespace WindowsFormsInfrastructure {

   using System;
   using System.Runtime.InteropServices;
   using System.Windows.Forms;
   using Infrastructure;
   
   /// <summary>
   /// This class is a workaround that allows minimized windows to recieve messages.
   /// </summary>
   /// <see cref="http://stackoverflow.com/questions/6786891/wndproc-how-to-get-window-messages-when-form-is-minimized/7033382#7033382"/>
   public class MessageWindow : Form {
      
      private readonly Form Form;
      private readonly string WantedMessage;
      private readonly int WantedMessageId;
      private readonly Action FormCallback;

      public MessageWindow(Form form, string windowName, string wantedMessage, Action formCallback) {
         Form = form;
         FormCallback = formCallback;
         this.Text = windowName;
         WantedMessage = wantedMessage;
         WantedMessageId = Win32WindowMessengerWrapper.GetMessageId(WantedMessage);
         var accessHandle = this.Handle;         
      }

      protected override void OnHandleCreated(EventArgs e) {
         base.OnHandleCreated(e);
         ChangeToMessageOnlyWindow();         
      }

      private void ChangeToMessageOnlyWindow() {
         // see http://msdn.microsoft.com/en-us/library/ms632599(VS.85).aspx#message_only
         IntPtr HWND_MESSAGE = new IntPtr(-3);
         SetParent(this.Handle, HWND_MESSAGE);         
      }

      [DllImport("user32.dll")]
      static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

      [DllImport("User32.dll")]
      public static extern Int32 SetForegroundWindow(int hWnd);

      protected override void WndProc(ref Message receivedMessage) {
         if (receivedMessage.Msg == WantedMessageId) {
            FormCallback();
            var handle = Form.Handle.ToInt32();
            SetForegroundWindow(handle);
         }
         base.WndProc(ref receivedMessage);
      }
   }
}
